import * as fs from 'fs-extra';
import * as path from 'path';
import {
  IconifyIcon,
  IconifyUsageStats,
  IconifyAnalysisOptions,
  VueFileIconMatch
} from '../types/iconify';

/**
 * Iconify 图标分析器
 * 分析 Vue 项目中使用的 Iconify 图标
 */
export class IconifyAnalyzer {
  private defaultOptions: Required<IconifyAnalysisOptions> = {
    recursive: true,
    extensions: ['.vue', '.js', '.ts', '.jsx', '.tsx'],
    ignoreDirs: ['node_modules', '.git', 'dist', 'build'],
    outputFormat: 'js',
    generateTypes: true
  };

  /**
   * 分析目录中的 Iconify 图标使用情况
   */
  async analyzeDirectory(
    directory: string,
    options: IconifyAnalysisOptions = {}
  ): Promise<IconifyUsageStats> {
    const opts = { ...this.defaultOptions, ...options };
    const stats: IconifyUsageStats = {
      icons: new Map(),
      collections: new Map(),
      totalIcons: 0,
      totalUsage: 0,
      totalFiles: 0,
      filesWithIcons: 0
    };

    try {
      const files = await this.getFiles(directory, opts);
      stats.totalFiles = files.length;

      console.log(`正在扫描 ${files.length} 个文件...`);

      for (const filePath of files) {
        const matches = await this.analyzeFile(filePath);

        if (matches.length > 0) {
          stats.filesWithIcons++;

          for (const match of matches) {
            this.recordIcon(stats, match.icon, filePath);
          }
        }
      }

      // 计算最终统计
      stats.totalIcons = stats.icons.size;
      stats.totalUsage = Array.from(stats.icons.values())
        .reduce((sum, icon) => sum + icon.usageCount, 0);

    } catch (error) {
      throw new Error(`分析目录失败: ${error instanceof Error ? error.message : String(error)}`);
    }

    return stats;
  }

  /**
   * 获取目录下的所有匹配文件
   */
  private async getFiles(directory: string, options: Required<IconifyAnalysisOptions>): Promise<string[]> {
    const files: string[] = [];

    async function scanDir(dir: string): Promise<void> {
      try {
        const items = await fs.readdir(dir);

        for (const item of items) {
          const fullPath = path.join(dir, item);
          const stat = await fs.stat(fullPath);

          if (stat.isDirectory()) {
            if (!options.ignoreDirs.includes(item)) {
              await scanDir(fullPath);
            }
          } else if (stat.isFile()) {
            const ext = path.extname(item);
            if (options.extensions.includes(ext)) {
              files.push(fullPath);
            }
          }
        }
      } catch (error) {
        // 忽略无法访问的目录
        console.warn(`警告: 无法访问目录 ${dir}`);
      }
    }

    if (options.recursive) {
      await scanDir(directory);
    } else {
      const items = await fs.readdir(directory);
      for (const item of items) {
        const fullPath = path.join(directory, item);
        const stat = await fs.stat(fullPath);
        if (stat.isFile() && options.extensions.includes(path.extname(item))) {
          files.push(fullPath);
        }
      }
    }

    return files;
  }

  /**
   * 分析单个文件中的 Iconify 图标
   */
  private async analyzeFile(filePath: string): Promise<VueFileIconMatch[]> {
    const matches: VueFileIconMatch[] = [];

    try {
      const content = await fs.readFile(filePath, 'utf-8');
      const lines = content.split('\n');

      // Iconify 图标的常见模式
      const patterns = [
        // Vue component 模式: <Icon icon="mdi:home" />
        {
          regex: /<[^>]*\bicon\s*=\s*["']([^"']+)["'][^>]*>/gi,
          type: 'component' as const
        },
        // class 模式: i-mdi-home, i-material-symbols-home
        {
          regex: /i-([a-z0-9]+(?:-[a-z0-9]+)*)(?:\s|[^a-z0-9-]|$)/gi,
          type: 'class' as const
        },
        // 字符串模式: 'mdi:home', "mdi:home"
        {
          regex: /["']([a-z][a-z0-9-]*):([a-z0-9-]+)["']/gi,
          type: 'string' as const
        },
        // 属性模式: icon="mdi:home", :icon="'mdi:home'"
        {
          regex: /(?:^|\s)(?:icon|iconName)\s*=\s*["']([^"']+)["']/gim,
          type: 'attribute' as const
        },
        // CSS 背景图模式
        {
          regex: /--iconify:\s*["']([^"']+)["']/gi,
          type: 'attribute' as const
        }
      ];

      for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {
        const line = lines[lineIndex];

        for (const pattern of patterns) {
          let match;
          while ((match = pattern.regex.exec(line)) !== null) {
            let iconValue = match[1] || match[0];

            // 提取图标名称，确保格式为 prefix:icon
            const iconMatch = iconValue.match(/([a-z0-9-]+):([a-z0-9-]+)/);
            if (iconMatch) {
              matches.push({
                icon: `${iconMatch[1]}:${iconMatch[2]}`,
                position: {
                  line: lineIndex + 1,
                  column: match.index! + 1
                },
                type: pattern.type,
                context: line.trim()
              });
            }
          }
        }
      }

    } catch (error) {
      console.warn(`警告: 无法读取文件 ${filePath}`);
    }

    return matches;
  }

  /**
   * 记录图标使用情况
   */
  private recordIcon(stats: IconifyUsageStats, iconName: string, filePath: string): void {
    const parts = iconName.split(':');
    if (parts.length !== 2) return;

    const [prefix, icon] = parts;

    // 更新图标信息
    if (!stats.icons.has(iconName)) {
      stats.icons.set(iconName, {
        name: iconName,
        prefix,
        icon,
        files: [],
        usageCount: 0
      });
    }

    const iconData = stats.icons.get(iconName)!;
    iconData.usageCount++;

    if (!iconData.files.includes(filePath)) {
      iconData.files.push(filePath);
    }

    // 更新集合信息
    if (!stats.collections.has(prefix)) {
      stats.collections.set(prefix, new Set());
    }
    stats.collections.get(prefix)!.add(icon);
  }

  /**
   * 获取所有唯一的前缀
   */
  getUniquePrefixes(stats: IconifyUsageStats): string[] {
    return Array.from(stats.collections.keys()).sort();
  }

  /**
   * 按使用频率排序图标
   */
  getIconsByUsage(stats: IconifyUsageStats): IconifyIcon[] {
    return Array.from(stats.icons.values())
      .sort((a, b) => b.usageCount - a.usageCount);
  }
}